using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Xna.Framework;
using HappySprite.Simulation;

namespace HappySprite.Tests
{
    [TestClass]
    public class CollisionTests
    {
        [TestMethod]
        public void BoxBoxCollisionTest()
        {
            World world = new World();
            Body box1 = new Body();
            box1.CollisionShape = Box.CreateFromSize(10f, 10f);
            box1.CollisionDetails = CollisionDetails.Full;

            Body box2 = new Body();
            box2.CollisionShape = Box.CreateFromSize(10f, 10f);
            box2.CollisionDetails = CollisionDetails.Full;
            box2.Transform.Position = new Vector2(9f, 9f);

            box1.Collision += delegate(CollisionEventArgs e)
            {
                Assert.IsTrue(true);
            };

            world.Add(box1);
            world.Add(box2);
            world.Update(0f);
        }

        [TestMethod]
        public void CircleCircleTest()
        {
            World world = new World();

            Body body1 = new Body();
            body1.CollisionShape = new Circle(50f);
            body1.CollisionDetails = CollisionDetails.Full;
            body1.Transform.Position = new Vector2(0f, 50f);

            Body body2 = new Body();
            body2.CollisionShape = new Circle(50f);
            body2.CollisionDetails = CollisionDetails.Full;
            body2.Transform.Position = new Vector2(0f, 148f);

            bool collisionOccured = false;

            body1.Collision += delegate(CollisionEventArgs e)
            {
                collisionOccured = true;
                AssertExtensions.AreEqual(Vector2.UnitY, e.Normal);
                AssertExtensions.AreEqual(2f, e.Depth);
                AssertExtensions.AreEqual(new Vector2(0f, 99f), e.ContactPoint);
            };

            world.Add(body1);
            world.Add(body2);
            world.Update(0f);

            Assert.IsTrue(collisionOccured);
        }

        [TestMethod]
        public void CircleCircleTest2()
        {
            World world = new World();

            Body body1 = new Body();
            body1.CollisionShape = new Circle(400f);
            body1.CollisionDetails = CollisionDetails.Full;
            body1.Transform.Position = new Vector2(401f, -10f);
            body1.Transform.Rotation = 1f;

            Body body2 = new Body();
            body2.CollisionShape = new Circle(50f);
            body2.CollisionDetails = CollisionDetails.Full;
            body2.Transform.Position = new Vector2(400f, 439.6059f);

            bool collisionOccured = false;

            body1.Collision += delegate(CollisionEventArgs e)
            {
                collisionOccured = true;
                AssertExtensions.AreEqual(new Vector2(-0.002224165f, 0.9999976f), e.Normal);
                AssertExtensions.AreEqual(new Vector2(400.1108f, 389.8025f), e.ContactPoint);
            };

            world.Add(body1);
            world.Add(body2);
            world.Update(0f);

            Assert.IsTrue(collisionOccured);
        }

        [TestMethod]
        public void CircleBoxTest()
        {
            World world = new World();

            Body body1 = new Body();
            body1.CollisionShape = new Circle(10f);
            body1.CollisionDetails = CollisionDetails.Full;
            body1.Transform.Position = new Vector2(-5f, 17.5f);

            Body body2 = new Body();
            body2.CollisionShape = new Box(10f, 10f);
            body2.CollisionDetails = CollisionDetails.Full;
            body2.Transform.Rotation = MathHelper.PiOver2;

            bool collisionOccured = false;

            body1.Collision += delegate(CollisionEventArgs e)
            {
                collisionOccured = true;
                AssertExtensions.AreEqual(-Vector2.UnitY, e.Normal);
                AssertExtensions.AreEqual(new Vector2(-5f, 10f), e.ContactPoint);
            };

            world.Add(body1);
            world.Add(body2);
            world.Update(0f);

            Assert.IsTrue(collisionOccured);
        }

        [TestMethod]
        public void CircleBoxTest2()
        {
            World world = new World();

            Body body1 = new Body();
            body1.CollisionShape = new Circle(10f);
            body1.CollisionDetails = CollisionDetails.Full;
            body1.Transform.Position = new Vector2(-12.5f, 12.5f);

            Body body2 = new Body();
            body2.CollisionShape = new Box(10f, 10f);
            body2.CollisionDetails = CollisionDetails.Full;
            body2.Transform.Rotation = MathHelper.ToRadians(45f);

            bool collisionOccured = false;

            body1.Collision += delegate(CollisionEventArgs e)
            {
                collisionOccured = true;
                AssertExtensions.AreEqual(new Vector2(0.7071068f, -0.7071068f), e.Normal);
                AssertExtensions.AreEqual(new Vector2(-7.071068f, 7.071068f), e.ContactPoint);
            };

            world.Add(body1);
            world.Add(body2);
            world.Update(0f);

            Assert.IsTrue(collisionOccured);
        }

        [TestMethod]
        public void CircleHalfPlaneTest()
        {
            World world = new World();

            Body body1 = new Body();
            body1.CollisionShape = new Circle(10f);
            body1.CollisionDetails = CollisionDetails.Full;
            body1.Transform.Position = new Vector2(0f, 7.5f);

            Body body2 = new Body();
            body2.CollisionShape = new HalfPlane(Vector2.UnitY);
            body2.CollisionDetails = CollisionDetails.Full;

            bool collisionOccured = false;

            body1.Collision += delegate(CollisionEventArgs e)
            {
                collisionOccured = true;
                AssertExtensions.AreEqual(-Vector2.UnitY, e.Normal);
                AssertExtensions.AreEqual(2.5f, e.Depth);
                AssertExtensions.AreEqual(new Vector2(0f, -2.5f), e.ContactPoint);
            };

            world.Add(body1);
            world.Add(body2);
            world.Update(0f);

            Assert.IsTrue(collisionOccured);
        }
    }
}
